package com.nightcolor.im.framework;


import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

public class ScrolledMainView extends ViewGroup {
	
	private int mMenuWidth = 0;
	
	private VelocityTracker mVelocityTracker;   
	private Scroller  mScroller;                         
	private int mCurScreen = 0;
	private float mLastMotionX;
	private float mLastMotionY;
	
	private int mTouchSlop;
    private int mMaximumVelocity;
	
    private boolean mIsDragging = false;
    private boolean mEnableSlide = true;
    
    private boolean mCanDragMove = true;
    
    private MenuSlideChangeListener mMenuSlideChangeListener;
    
	public ScrolledMainView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
		// TODO Auto-generated constructor stub
	}

	public ScrolledMainView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
		// TODO Auto-generated constructor stub
	}

	public ScrolledMainView(Context context) {
		super(context);
		init();
		// TODO Auto-generated constructor stub
	}
	
	private void init() {
		mScroller = new Scroller(getContext());
		ViewConfiguration vc = ViewConfiguration.get(getContext());
		mMaximumVelocity = vc.getScaledMaximumFlingVelocity();
		mTouchSlop = vc.getScaledTouchSlop();
		mCurScreen = 1;
	} 
	
	public void setMenuWidth(int menuWidth) {
		this.mMenuWidth = menuWidth;
	}
	
	public void setCanDragMove(boolean canDragMove) {
		this.mCanDragMove = canDragMove;
	}
	
	public boolean isMenuVisible() {
		if (mCurScreen == 0) {
			return true;
		}
		return false;
	}
	
	public void showMenu() {
		nextScreen(0);
	}
	
	public void hideMenu() {
		nextScreen(1);
	}
	
	public void setEnableSlide(boolean enable) {
		mEnableSlide = enable;
	}
	
	public void setMenuSlideChangeListener(MenuSlideChangeListener l) {
		mMenuSlideChangeListener = l;
	}
	
	@Override
	protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
		// TODO Auto-generated method stub
		Log.d("yese", "onLayout 1");
		if (!changed) {
			return;
		}
		Log.d("yese", "onLayout 2");
		View menuView = getChildAt(0);
		int menuH = menuView.getMeasuredHeight();
		menuView.layout(0, 0, mMenuWidth, menuH);
		
		View contentView = getChildAt(1);
		int contentH = contentView.getMeasuredHeight();
		int contentW = contentView.getMeasuredWidth();
		contentView.layout(mMenuWidth, 0, mMenuWidth + contentW, contentH);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		Log.d("yese", "onDraw");
		super.onDraw(canvas);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		
		int width = MeasureSpec.getSize(widthMeasureSpec);
		int height = MeasureSpec.getSize(heightMeasureSpec);
		
		View menuView = getChildAt(0);
		menuView.measure(MeasureSpec.makeMeasureSpec(mMenuWidth, MeasureSpec.EXACTLY), 
				MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
		
		View contentView = getChildAt(1);
		contentView.measure(widthMeasureSpec, heightMeasureSpec);
		
		if (mCurScreen == 0) {
//			Log.d("yese", "onMeasure mCurScreen == 0");
			scrollTo(0, 0);
		}
		else if (mCurScreen == 1) {
//			Log.d("yese", "onMeasure mCurScreen == 1");
			scrollTo(mMenuWidth, 0);
		}
	}

	@Override
	public void computeScroll() {
		if (mScroller.computeScrollOffset()) {
//			Log.d("yese", "computeScroll x=" + mScroller.getCurrX() + " y=" + mScroller.getCurrY());
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); 
            postInvalidate(); 
		}
	}
	
	private boolean canMove(int deltaX) {
//		Log.d("layout", "canMove()");
		if (deltaX >= 0 && mCurScreen == 1) { //右
			return true;
		}
		else if (deltaX <= 0 && mCurScreen == 0) { //左
			return true;
		}
		return false;
	}
	
	private void nextScreen(int screen) {
		mScroller.abortAnimation();
		if (screen == 0) {
//			Log.d("yese", "nextScreen screen = " + screen);
			int delta = 0 - getScrollX();   
            mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2);              
	        mCurScreen = screen;
	        if (mMenuSlideChangeListener != null) {
	        mMenuSlideChangeListener.onSlideChange(true);
	        }
	        invalidate();
		}
		else if (screen == 1) {
//			Log.d("yese", "nextScreen screen = " + screen);
			int delta = mMenuWidth - getScrollX();   
            mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2);              
	        mCurScreen = screen;
	        if (mMenuSlideChangeListener != null) {
	        mMenuSlideChangeListener.onSlideChange(false);
	        }
	        invalidate();
		}
    }
	
	private void moveTarget() {
		int div = mMenuWidth / 2;
//		Log.d("yese", "moveTarget getScrollX() = " + getScrollX() + " div = " + div);
		if (getScrollX() <= div) {
			if (mMenuSlideChangeListener != null) {
			mMenuSlideChangeListener.onSlideChange(true);
			}
			nextScreen(0);
		}
		else {
			if (mMenuSlideChangeListener != null) {
				mMenuSlideChangeListener.onSlideChange(false);
			}
			nextScreen(1);
		}
	}
	
	@Override
	public boolean onInterceptTouchEvent(MotionEvent event) {
		
		if (!mCanDragMove) {
			return false;
		}
		
		int action = event.getAction();
		float x = event.getX();
		float y = event.getY();
		
		if (action == MotionEvent.ACTION_MOVE && mIsDragging) {
//			Log.d("yese", "onInterceptTouchEvent return true1");
			return true;
		}
		
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			mLastMotionX = x;
			mLastMotionY = y;
			if (!mScroller.isFinished()) {
				mIsDragging = true;
			}else {
				mIsDragging = false;
			}
			break;

		case MotionEvent.ACTION_MOVE:
			if (!mEnableSlide) {
				return false;
			}
			int deltaX = (int)(x - mLastMotionX);
			int deltaY = (int)(y - mLastMotionY);
			
			if (Math.abs(deltaX) >= mTouchSlop
					&& Math.abs(deltaY) < mTouchSlop
					&& Math.abs(deltaX) >= Math.abs(deltaY) 
					&& canMove(deltaX)) {
				mIsDragging = true;
			}
			else {
				mIsDragging = false;
			}
			break;
			
		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:
			mIsDragging = false;
			break;
		}
//		Log.d("yese", "onInterceptTouchEvent return " + mIsDragging + "2");
		return mIsDragging;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		
		if (!mCanDragMove) {
			return false;
		}
		
		int action = event.getAction();
		float x = event.getX();
		float y = event.getY();
		
		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(event);
		
		switch (action) {
		case MotionEvent.ACTION_DOWN:
//			Log.d("yese", "onTouchEvent ACTION_DOWN");
			mLastMotionX = x;
			mLastMotionY = y;
			return true;

		case MotionEvent.ACTION_MOVE:
//			Log.d("yese", "onTouchEvent ACTION_MOVE");
			int deltaX = (int) (mLastMotionX - x);
			if((getScrollX() > 0 || deltaX > 0 ) 
					&& (getScrollX() < getWidth() || deltaX < 0)) {
				mLastMotionX = x;
				mLastMotionY = y;
//				scrollBy(deltaX, 0);
			}
			return true;
			
		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:
//			Log.d("yese", "onTouchEvent ACTION_UP");
			mIsDragging = false;
			int velocityX = 0;
			mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
			velocityX = (int)mVelocityTracker.getXVelocity();
			
//			Log.d("yese", "velocityX = " + velocityX 
//					+ "  mMinimumVelocity = " + mMinimumVelocity);
			
			if (!mScroller.isFinished()) {
				mScroller.abortAnimation();
				mScroller.forceFinished(true);
			}
			//move right
			if (/*velocityX > mMinimumVelocity && */mCurScreen == 1) {
//				Log.d("yese", "onTouchEvent ACTION_UP nextScreen(0)");
				nextScreen(0);
			}
			//move right
			else if (/*velocityX < -mMinimumVelocity && */mCurScreen == 0) {
//				Log.d("yese", "onTouchEvent ACTION_UP nextScreen(1)");
				nextScreen(1);
			}
			else {
				moveTarget();
//				Log.d("yese", "onTouchEvent ACTION_UP moveTarget()");
			}
			if (mVelocityTracker != null) {
				mVelocityTracker.recycle();
				mVelocityTracker = null;
			}
			return true;
		}
		return false;
	}
	
}